<?php

/**
 * Base Controller Class
 * 
 * @author Ben Rowe
 */
class Controller
{
	/**
	 * stores the view name to be loaded by the getView() method
	 *
	 * @access private
	 * @var string
	 */
	var $_view;
	
	/**
	 * The name of the requested section, calculated by the _getName() method
	 *
	 * @access private
	 * @var string
	 */
	var $_name;
	
	/**
	 * hash of data stored by the controllers actions
	 * This hash is used by the view to build dynamic pages
	 *
	 * @access private
	 * @var array
	 */
	var $_hash = array();
	
	/**
	 * Controller
	 * Get the name of the section the user has requested,
	 * ensure we have an index method, then load the
	 * action requested
	 * 
	 * @access public
	 * @return Controller
	 */
	function Controller()
	{
		// make sure the parent class has at least a default action!
		$this->_getName();
		if(!method_exists($this, 'index')) {
			die('Requested section ('.$this->_name.') is not valid, does not contain default action!');
		}
		$this->_loadAction();	
	}
	
	/**
	 * Get the name of the section requested by the user
	 *
	 * @access private
	 * @return boolean
	 */
	function _getName()
	{
		$name = get_class($this);
		$this->_name = substr($name, 0, strpos($name, '_'));
		return true;
	}
	
	/**
	 * Try to load the action the visitor has requested.
	 * If the action doesn't exist, default to the index action!
	 * 
	 * @access private
	 * @return boolean
	 */
	function _loadAction()
	{
		$action = $this->_getAction();
		if(!method_exists($this, $action)) {
			$action = 'index';
		}
		$this->$action();
		return true;
	}
	
	/**
	 * Get the action the user has requested
	 *
	 * @access private
	 * @return string
	 */
	function _getAction()
	{
		return isset($_REQUEST['action']) ? $_REQUEST['action'] : 'index';
	}
	
	/**
	 * Get a instance of the view the controller has selected
	 * 
	 * @access public
	 * @return Object
	 */
	function getView()
	{
		if(!is_null($this->_view)) {
			$name = !empty($this->_name) ? strtolower($this->_name).'_' : null;
			require_once 'app'.DS.'views'.DS.$name.$this->_view.EXT;
			$className = $name.$this->_view.'_View';
			return new $className($this->_hash);
		}
		die($this->_name.'_Controller::'.$this->_getAction().': A view must be declaired.');
	}
	
	/**
	 * Set the view to be loaded by the controller
	 *
	 * @access private
	 * @param string $view
	 * @return boolean
	 */
	function _setView($view)
	{
		$this->_view = $view;
		return true;
	}
	
	/**
	 * Set a key/value into the controller data hash.
	 * This hash is automatically passed onto the view
	 * so that it can be used for displaying dynamic content within the view
	 *
	 * @access public
	 * @param string $key
	 * @param mixed $value
	 * @return boolean
	 */
	function _set($key, $value)
	{
		$this->_hash[$key] = $value;
		return true;
	}
	
	/**
	 * Redirect the application to a new url
	 * The url should start from the php initial access point
	 *
	 * @example index.php?section=foo&action=bar
	 *
	 * @access public
	 * @param string $url
	 * @return null
	 */
	function redirect($url= 'index.php')
	{
		$base_url = $this->_baseURL();
		header('location: '.$base_url.$url);
		exit;
	}
	
	/**
	 * Generates a base url for the current application
	 * 
	 * @access private
	 * @return string
	 */
	function _baseURL()
	{
		$host = $_SERVER['HTTP_HOST'];
		$script_name = pathinfo($_SERVER['SCRIPT_NAME'], PATHINFO_DIRNAME);
		return 'http://'.$host.$script_name.'/';
	}
	
	/**
	 * Check if the provided 'permissions' are available for this controller
	 *
	 * @todo implement $join into the proceedure.
	 * @access public
	 * @param mixed $permissions either a string or array of strings of the permissions to check
	 * @param string $join determins how multiple permissions are processed (currently unimplemented)
	 * @return boolean
	 */
	function actionSecure($permissions, $join = 'OR')
	{
		global $security;
		if(!is_array($permissions)) $permissions = array($permissions);
		// loop through each of the permissions and prefix the controller name to it
		foreach($permissions as $k=>$v) {
			$permissions[$k] = strtolower($this->_name).'_'.$v;
		}
		if(!$security->hasPermission($permissions)) {
			// display the access denyed view!
			$this->_name = '';
			$this->_set('permissions', $permissions);
			$this->_set('join', $join);
			$this->_setView('access_denied');
			$this->getView();exit;
			return false;
		}
		return true;
	}
}

?>
